package com.yeskery.nut.event;

import com.yeskery.nut.core.Order;
import com.yeskery.nut.core.ThreadPool;

import java.util.*;
import java.util.concurrent.Executor;
import java.util.function.Predicate;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * 默认的事件广播器
 * @author Yeskery
 * 2023/8/8
 */
public class DefaultApplicationEventMulticaster implements ApplicationEventMulticaster {

    /** 日志对象 */
    private static final Logger logger = Logger.getLogger(DefaultApplicationEventMulticaster.class.getName());

    /** 监听器集合 */
    private final Collection<ApplicationListener<?>> applicationListeners = new ArrayList<>(64);

    /** 缓存监听map */
    private final Map<Class<?>, List<SmartApplicationListener>> cacheListenerMap = new HashMap<>(16);

    /** 默认线程池对象 */
    private final Executor defaultExecutor;

    /** 线程池对象 */
    private Executor executor;

    /**
     * 构建默认的事件广播器
     * @param defaultExecutor 默认线程池对象
     */
    public DefaultApplicationEventMulticaster(Executor defaultExecutor) {
        this.defaultExecutor = defaultExecutor;
    }

    @Override
    public void addApplicationListener(ApplicationListener<?> listener) {
        if (!applicationListeners.contains(listener)) {
            if (applicationListeners.add(listener)) {
                cacheListenerMap.clear();
            }
        }
    }

    @Override
    public void removeApplicationListener(ApplicationListener<?> listener) {
        if (applicationListeners.remove(listener)) {
            cacheListenerMap.clear();
        }
    }

    @Override
    public void removeApplicationListeners(Predicate<ApplicationListener<?>> predicate) {
        if (applicationListeners.removeIf(predicate)) {
            cacheListenerMap.clear();
        }
    }

    @Override
    public void removeAllListeners() {
        applicationListeners.clear();
        cacheListenerMap.clear();
    }

    @Override
    @SuppressWarnings("rawtypes")
    public void multicastEvent(ApplicationEvent event) {
        for (ApplicationListener applicationListener : getSupportApplicationListeners(event)) {
            if (executor != null) {
                executor.execute(() -> doInvokeListener(applicationListener, event));
            } else {
                doInvokeListener(applicationListener, event);
            }
        }
    }

    /**
     * 设置线程池对象
     * @param executor 线程池对象
     */
    public void setExecutor(Executor executor) {
        this.executor = executor;
    }

    /**
     * 设置线程池对象
     * @param threadPool 线程池对象
     */
    public void setExecutor(ThreadPool threadPool) {
        this.executor = threadPool.getThreadPool();
    }

    /**
     * 使用默认线程池对象，异步处理所有事件回调
     */
    public void useDefaultExecutor() {
        this.executor = defaultExecutor;
    }

    /**
     * 获取指定的事件支持的所有事件监听器
     * @param event 事件
     * @return 指定的事件支持的所有事件监听器
     */
    private List<SmartApplicationListener> getSupportApplicationListeners(ApplicationEvent event) {
        List<SmartApplicationListener> listeners = cacheListenerMap.get(event.getClass());
        if (listeners == null) {
            synchronized (cacheListenerMap) {
                listeners = cacheListenerMap.get(event.getClass());
                if (listeners == null) {
                    listeners = new ArrayList<>(32);
                    for (ApplicationListener<?> applicationListener : applicationListeners) {
                        SmartApplicationListener smartApplicationListener;
                        if (applicationListener instanceof SmartApplicationListener) {
                            smartApplicationListener = (SmartApplicationListener) applicationListener;
                        } else {
                            smartApplicationListener = new SmartApplicationListenerAdapter(applicationListener);
                        }
                        if (smartApplicationListener.supportEventType(event.getClass())) {
                            listeners.add(smartApplicationListener);
                        }
                    }
                    listeners.sort(Comparator.comparing(Order::getOrder));
                    cacheListenerMap.put(event.getClass(), listeners);
                }
            }
        }
        return listeners;
    }

    /**
     * 执行事件监听器的回调方法
     * @param applicationListener 事件监听器
     * @param event 事件
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    private void doInvokeListener(ApplicationListener applicationListener, ApplicationEvent event) {
        try {
            applicationListener.onApplicationEvent(event);
        } catch (Exception e) {
            logger.logp(Level.SEVERE, applicationListener.getClass().getName(), "onApplicationEvent",
                    "ApplicationListener Event Invoke Method Execute Fail.", e);
        }
    }
}
